﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AD.Pms.Core;
using AD.Pms.Core.ClientApi;
using AD.Pms.Core.EnumHelper;
using AD.Pms.DataBase.Models.ZC_Config;
using AD.Pms.DataBase.Models.ZC_Log;
using AD.Pms.DataBase.Models.ZC_Member;
using AD.Pms.DataBase.Models.ZC_Order;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace AD.Pms.Api.Controllers.V1
{
    [Route("api/v1/[controller]/[action]")]
    [ApiController]
    public class ReportController : ControllerBase
    {
        private readonly ZC_configContext _zC_ConfigContext;
        private readonly ZC_MemberContext _zC_MemberContext;
        private readonly ZC_OrderContext _zC_OrderContext;
        private readonly ZC_LogContext _zC_LogContext;
        private readonly Utils _utils;

        public ReportController(ZC_configContext zC_ConfigContext, Utils utils, ZC_MemberContext zC_MemberContext,
            ZC_OrderContext zC_OrderContext, ZC_LogContext zC_LogContext)
        {
            _zC_ConfigContext = zC_ConfigContext;
            _zC_MemberContext = zC_MemberContext;
            _utils = utils;
            _zC_OrderContext = zC_OrderContext;
            _zC_LogContext = zC_LogContext;
        }

        /// <summary>
        /// 用户注册报表
        /// </summary>
        /// <param name="starttime">开始时间</param>
        /// <param name="endtime">结束时间</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public async Task<JsonResult> UserRegisteReport(DateTime? starttime, DateTime? endtime, string type)
        {
            var res = new ApiResult<Dictionary<string, int>>();
            starttime = starttime ?? DateTime.Now.AddDays(-7).Date;
            endtime = endtime ?? DateTime.Now.Date;
            var query = from item in _zC_MemberContext.TblUserAccount
                where item.CreateTime >= starttime && item.CreateTime <= endtime
                select item;
            if (type == "day")
            {
                var result = await query.GroupBy(x => x.CreateTime.HasValue ? x.CreateTime.Value.Date : x.CreateTime)
                    .Select(x => new
                    {
                        time = x.Key.HasValue ? x.Key.ToString() : "",
                        count = x.Count()
                    }).ToListAsync();
                res.data = result.ToDictionary(x => x.time, x => x.count);
                return new JsonResult(res);
            }
            else if (type == "week")
            {
                var result =
                    (await query.Select(x => x.CreateTime.HasValue ? (x.CreateTime.Value - starttime).Value.Days : 0)
                        .ToListAsync()).GroupBy(x => x / 7)
                    .Select(x => new
                    {
                        time = x.Key,
                        count = x.Count()
                    }).ToDictionary(x => $"第{x.time}周", x => x.count);
                res.data = result;
                return new JsonResult(res);
            }
            else if (type == "season")
            {
                var result =
                    (await query.Select(x => x.CreateTime.HasValue ? x.CreateTime.Value.Month / 4 : 0).ToListAsync())
                    .GroupBy(x => x)
                    .Select(x => new
                    {
                        time = x.Key,
                        count = x.Count()
                    }).ToDictionary(x => $"第{x.time}季", x => x.count);
                res.data = result;
                return new JsonResult(res);
            }
            else if (type == "year")
            {
                var result = (await query.Select(x => x.CreateTime.HasValue ? x.CreateTime.Value.Year : 0)
                        .GroupBy(x => x).ToListAsync())
                    .Select(x => new
                    {
                        time = x.Key,
                        count = x.Count()
                    }).ToDictionary(x => $"第{x.time}年", x => x.count);
                res.data = result;
                return new JsonResult(res);
            }
            else
            {
                res.statusCode = (int) ApiEnum.ParameterError;
                res.message = "该类型不支持";
                return new JsonResult(res);
            }
        }

        /// <summary>
        /// 用户充值报表
        /// </summary>
        /// <returns></returns>
        public async Task<JsonResult> UserChargeReport()
        {
            var res = new ApiResult<Dictionary<string, object>>();
            var platformtask = _zC_OrderContext.TblPayInfo.GroupBy(x => x.PayPlatform)
                .Select(x => new {pplatform = x.Key, payamount = x.Sum(d => d.PayAmount)}).ToListAsync();
            var totaltask = _zC_OrderContext.TblPayInfo.SumAsync(x => x.PayAmount);
            await Task.WhenAll(platformtask, totaltask);
            var data = new Dictionary<string, object>();
            data["total"] = await totaltask;
            data["platform"] = await platformtask;
            res.data = data;
            return new JsonResult(res);
        }


        public async Task<JsonResult> MembershipDueReport(DateTime? starttime, DateTime? endtime)
        {
            var res = new ApiResult<Dictionary<DateTime?, int>>();
            starttime = starttime ?? DateTime.Now.AddDays(-7).Date;
            endtime = endtime ?? DateTime.Now.Date;

            var result = from item in _zC_MemberContext.TblUserPermission
                where item.EndTime >= starttime && item.EndTime <= endtime
                group item by item.EndTime.HasValue ? item.EndTime.Value.Date : item.EndTime
                into g
                select new
                {
                    endtime = g.Key,
                    count = g.Count()
                };
            var data = (await result.ToListAsync()).ToDictionary(x => x.endtime, x => x.count);
            res.data = data;
            return new JsonResult(res);
        }

        public async Task<JsonResult> UserLoginReportByDate(DateTime? starttime, DateTime? endtime)
        {
            var res = new ApiResult<Dictionary<DateTime?, int>>();
            starttime = starttime ?? DateTime.Now.AddDays(-7).Date;
            endtime = endtime ?? DateTime.Now.Date;

            var result = await _zC_LogContext.TblUserLoginLog
                .Where(x => x.CreateTime >= starttime && x.CreateTime <= endtime)
                .GroupBy(x => x.CreateTime.HasValue ? x.CreateTime.Value.Date : x.CreateTime)
                .Select(g => new
                {
                    date = g.Key,
                    count = g.Count()
                }).ToDictionaryAsync(x => x.date, x => x.count);
            res.data = result;
            return new JsonResult(res);
        }

        public async Task<JsonResult> UserLoginReport(DateTime? starttime, DateTime? endtime, string type)
        {
            var res = new ApiResult<Dictionary<string, int>>();
            starttime = starttime ?? DateTime.Now.AddDays(-7).Date;
            endtime = endtime ?? DateTime.Now.Date;
            Func<TblUserLoginLog, string> getGroupString = x =>
            {
                if (type == "browser")
                {
                    return x.Browser;
                }
                else if (type == "location")
                {
                    return x.LoginLocation;
                }
                else
                {
                    return x.LoginDevice;
                }
            };
            var result = await _zC_LogContext.TblUserLoginLog
                .Where(x => x.CreateTime >= starttime && x.CreateTime <= endtime)
                .GroupBy(x => getGroupString(x))
                .Select(g => new
                {
                    data = g.Key,
                    count = g.Count()
                }).ToDictionaryAsync(x => x.data, x => x.count);
            res.data = result;
            return new JsonResult(res);
        }

        /// <summary>
        /// 搜索报表
        /// </summary>
        /// <param name="starttime">开始时间</param>
        /// <param name="endtime">结束时间</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException"></exception>
        public async Task<JsonResult> SearchReport(DateTime? starttime, DateTime? endtime, string type)
        {
            var res = new ApiResult<Dictionary<string, int>>();
            starttime = starttime ?? DateTime.Now.AddDays(-7).Date;
            endtime = endtime ?? DateTime.Now.Date;

            var result =
                _zC_LogContext.TblSearchHistory.Where(x => x.CreateTime >= starttime && x.CreateTime <= endtime);
            if (type == "count")
            {
                var data = await result.CountAsync();
                res.data = new Dictionary<string, int>() {{"count", data}};
                return new JsonResult(res);
            }
            else
            {
                Func<TblSearchHistory, string> groupFunc = x =>
                {
                    if (type == "type")
                    {
                        return x.SearchType?.ToString();
                    }
                    else if (type == "role")
                    {
                        return x.UserRole?.ToString();
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }
                };

                var data = await result.GroupBy(x => groupFunc(x))
                    .ToDictionaryAsync(x => x?.ToString(), x => x.Count());
                res.data = data;
                return new JsonResult(res);
            }
        }
    }
}